查看原文
其他

干货|不断打磨和提升——PC Web直播播放器技术演进

爱奇艺直播团队 爱奇艺技术产品团队 2019-06-13

0.导读

PC Web直播播放器(下文均称作 “播放器”)主要支撑爱奇艺直播频道下游戏直播、小剧场以及大型晚会、明星发布会等,同时也应用于内部直播、监播预览。播放器实现了不同设备、不同浏览器下,对不同封装格式的直播流的播放,以及对广告、多语言、弹幕等功能的拆分和整合。架构上,播放器先后经过了完全Flash,Flash和H5混合架构,以及业务逻辑完全H5化的三个过程。


经团队不断打磨,改造后的通用化播放器架构已经形成,播放能力的性能和可用性得以大幅提高,播放器的易用性和用户体验也在不断提升。下文将就直播播放器应对业务和技术环境的变化所做的实践,特别是整合播放器的设计和实现做详细介绍。

1.Flash时代

H5标准之前,Flash提供了主流的音视频播放解决方案。无论是基于TCP传输的RTMP,或者基于HTTP的FLV,Flash都提供了方便好用的接口,开发者基本不用关心编解码的细节。

播放器的主要内容都在业务逻辑的处理上,此时的架构比较简单。 


图1 Flash播放器架构图

2. 混合架构时代

HTML5标准发布以来,至2015年左右,主流浏览器(除IE外)基本都实现了对H5的支持。同时,Flash经常爆出安全和性能的问题,开发者社区活跃度下降。作为非标准时代的产物,Flash也到了落幕的时候:


1. 2016年,B站flv.js[^1]的出现提供了一种H5直播的可能

2. 2017年7月25日,Adobe宣告2020年之后不再更新和分发Flash[^2]

17年5月的时候,H5播放作为团队内部一个调研方向逐渐展开,Adobe声明发布之后,作为一个优先项目提上日程。此时整个播放器的架构设计成:

图2 混合播放器架构

PlayerSDK作为最外层的壳,是一些轻量级逻辑代码,提供与外部通信的接口和事件,并根据浏览器兼容性路由到不同的播放器上去。H5PlayerFlashPlayer相互独立,各自有自己的业务处理和播放引擎。

本阶段主要针对浏览器兼容性和体验上的问题进行打磨,比如在最新H5Player下可能出现的音画不同步、弱网直播延迟、浏览器拉流兼容、H5播放的QoS埋点和监控。同时将播放重心逐渐过渡到H5上来,Flash播放器作为一个兜底方案。

3. 整合播放器时代

3.0 问题和解决思路

H5Player上线以来,经历了大大小小的几次填坑之后,H5播放逐渐稳定。但是业务上的问题逐渐显现:

对于每一个产品需求,基本都要实现两份(Flash和H5),这直接导致了我们开发量的上升

与此同时,团队所负责的业务范围进一步扩大,新业务提出了更多的要求:

1. 需要支持更多封装格式和拉流方式

2. 需要支持移动设备的浏览观看

3. 需要处理多语言、广告等附加功能

新老业务两块主要业务线因为需求差异以及历史原因,分别是两个独立的的播放器;同时,每条业务线在低版本浏览器下,必须使用Flash播放器来支持播放和相关的上层业务。

面对这些现实问题,一个想法在团队内部产生:

我们能否把所有播放器整合起来,同时兼顾业务逻辑的扩展性?

最终整合播放器遵循了以下的设计思路和解决方案:

首先,我们提出“插件化”的概念,把各个业务的功能抽离成一个个插件,并使得各种插件在不同的业务形态上形成复用,从逻辑上消除了不同业务线或需求造成的播放器差异,只通过初始化配置的方式,选择不同的插件,就能达到实际需求

其次,我们提出“去Flash化”——实际结果就是把Flash的应用范围从独立播放器缩小为Flash播放内核,内核的上层统一使用JavaScript进行实现;这样就完全消除了每个业务需求都要在低版本上使用Flash再实现一次的成本。

另外,针对上述说的客户端场景不同,使用EngineSDK来做作为播放内核的统一代理,来包装不同场景下的多个内核,做到统一管理,并相互隔离。

3.1 播放器逻辑分层

播放器按照角色拆分为三层:

1. UniPlayer,SDK部分,负责与外部通信的接口,以及不同业务插件功能的配置和组合

2. PlayerCore, 供插件使用的轻量级公用接口,以及插件状态管理

3. Plugin,各个独立的业务逻辑,比如播控、播放引擎、弹幕等

图3 整合播放器逻辑分层

其中插件是主要业务单元和扩展单元。对于逻辑复杂的插件,其具体实现可以封装成一个小型的SDK,通过Pluginload方法动态加载。

```js /** * 插件管理基类 */ class PluginBase extends Emitter { constructor(container, player){}

//生命周期方法
load(){}
init(e){}
destroy(){}

//事件管理方法
addPlayerEvent(type, handler){}
removeAllPlayerEvents(){}

//状态管理方法
getState() {}
getType(){}

}

export default PluginBase; ```

3.2 插件通信

Plugin之间相互独立,无法直接通信。PluginPlayerCore之间进行双向通信。插件内部的状态保存到公共State组件里。

图4 插件通信与状态管理

```js /** * 引擎播放状态 */ class PlayStatus { constructor() { this.IDLE = 'idle'; this.PLAYING = 'playing'; this.PAUSED = 'paused'; this.ERROR = 'error'; this.SEEKING = 'seeking';

this._status = this.IDLE;
}

setStatus(status)
{
this._status = status;
}

getStatus()
{
return this._status;
}

isPlaying()
{
return this.getStatus() == this.PLAYING;
}

isPaused()
{
return this.getStatus() == this.PAUSED;
}

...

}

export default new PlayStatus(); ```

3.3 插件内部实现

插件根据其复杂度,可以是一个简单类,也可以独立成一个小型SDK。以播放引擎为例,不同的引擎基于引擎基类,包装了不同场景下的播放需求,以实现水平扩展;引擎SDK提供一个工厂方法创建引擎实例,EnginePlugin负责引擎实例的创建和管理。

  • HttpEngine负责HLS的播放

  • FlashEngine负责低版本浏览器下的播放

  • PtEngine负责自有格式直播流的播放

  • FlvEngine负责低延迟直播流的播放


图5 EngineSDK实现

3.4 视图插件的DOM容器管理

播放器DOM容器是外部创建的,播放器本身不应该改变容器宽高。所以每个插件通过垂直方向的层级划分来实现视图上的互不影响。

  • 插件容器都是绝对定位的div

  • 视图插件的层级预先定义

  • 不同视图插件的子元素层级不能交错


图6 插件DOM分层


元素拦截鼠标冒泡事件

对于低版本浏览器,如果插件功能无法由JavaScript实现,会回退成Flash版本。由于<object>元素会拦截鼠标事件,导致鼠标事件无法正常冒泡。如果上层<object>没有可见元素,需要设置为不可点击。

3.5 播放器整合后的阶段性小结


整合后带来的优势

1. 开发效率的提升。从四个播放器到一个,开发过程极大地简化,开发人员可以更加专注于功能的实现。同时可复用的逻辑上升为组件,进一步提升开发效率。

2. 可扩展性的增强。出现新的业务需求,只需增加插件。对于复杂的功能,可以实现为一个小型SDK,在SDK内部增加额外功能实现。


带来的局限性和取舍

1. 低级浏览器下的某些体验的缺失。比如不支持在IE11下进行播放器全屏显示,或者在更低的IE版本下,H5的样式可能会相比纯Flash播放器的样式观感上略显生涩一些。

2. 由于功能的拆解,从客观上来说会加载多一些的文件。


针对第一点,通过对用户浏览器的UA分析,高级浏览器占绝大多数,并且随着浏览器版本的迭代, 上述问题的影响也会越来越小。而第二点,在后续的迭代优化中,我们会延迟加载和播放相关度不高的模块,确保不影响用户看到视频首帧的时间。

4. 总结

经过改造后,通用化的播放器架构已经形成;作为一款直播播放器,我们的定位是,专注于提供高性能,高可用性的播放能力,并且不断打磨播放器的易用性和用户体验,提供适应不同场景下的功能插件,以此满足爱奇艺不同业务不同场景下的直播需求。


随着浏览器对WebAssembly等新技术的支持,H.265和AV1等Codec的出现,播放器仍将继续改进,满足用户对于流畅播放、以及高画质的追求。


参考链接

[^1]: flv.js, https://github.com/Bilibili/flv.js 

[^2]: Flash & The Future of Interactive Content, 

https://theblog.adobe.com/adobe-flash-update/

end

你可能还想看

搭建连接JS与C++的桥梁 - 爱奇艺RND框架之JS绑定

爱奇艺AI剪辑师到底能剪出怎样的视频?


扫一扫下方二维码,更多精彩内容陪伴你!

爱奇艺技术产品团队

简单想,简单做


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存